import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
import { id } from "date-fns/locale";
import { find } from "rxjs";
import { ChannelEntity } from "src/Entity/channel.entity";
import { GuestEntity } from "src/Entity/guest.entity";
import { LogEntity } from "src/Entity/log.entity";
import { OrderGuestEntity } from "src/Entity/order_guest.entity";
import { OrderPaymentEntity } from "src/Entity/order_payment.entity";
import { OrderRoomEntity } from "src/Entity/order_room.entity";
import { RoomEntity } from "src/Entity/room.entity";
import { RoomTypeEntity } from "src/Entity/roomType.entity";
import { UsersEntity } from "src/Entity/user.entity";
import { getManager, In, } from "typeorm";
import { OrderEntity } from "../Entity/order.entity";


@Injectable()
export class OrderService {
    constructor(

    ) { }

    async create(userId: number, orderEntity: OrderEntity) {
        // return userId;
        const _orderEntity = new OrderEntity();
        _orderEntity.orderNo = orderEntity.orderNo;
        _orderEntity.remark = orderEntity.remark;
        _orderEntity.startTime = orderEntity.startTime;
        _orderEntity.endTime = orderEntity.endTime;
        _orderEntity.payLog = orderEntity.payLog;
        _orderEntity.guest = orderEntity.guest;
        _orderEntity.roomType = orderEntity.roomType;
        _orderEntity.channel = orderEntity.channel;
        _orderEntity.userId = userId;
        // Object.keys(_orderEntity).forEach((item) => {
        //     if(typeof _orderEntity[item] !== 'function') {
        //         _orderEntity[item] = orderEntity[item];
        //     }
        // })

        const u = await OrderEntity.findOne({ where: { orderNo: orderEntity.orderNo } });
        if (u) {
            throw new HttpException({
                message: 'Order is exist',
                error: 'orderNo must be unique',
            },
                HttpStatus.BAD_REQUEST);
        }
        let content: string = "【" + orderEntity.guest[0].yourname + "-" + orderEntity.guest[0].phone + "-" + orderEntity.guest[0].card + "】" + "《" + orderEntity.channel.orderSource + "》办理预定" + "\n";
        content = content + orderEntity.startTime + "入住" + "\n预定:";



        // orderEntity.amount = orderEntity.amount * 100;
        // orderEntity.paidAmount = orderEntity.paidAmount * 100;
        // orderEntity.deposit = orderEntity.deposit * 100;
        // orderEntity.receivedDeposit = orderEntity.receivedDeposit * 100;
        // orderEntity.returnDeposit = orderEntity.returnDeposit * 100;

        await getManager().transaction(async manager => {
            // const order = await OrderEntity.save(orderEntity);

            const order = await manager.save(_orderEntity);

            const date = new Date();
            // const time = format(date,'YYYY-MM-DD HH:mm:ss');
            const log = new LogEntity();
            log.orderId = order.id;
            log.gmt_create = date;

            const channelEntity = new ChannelEntity();
            if (orderEntity.channel) {
                channelEntity.orderId = order.id;
                channelEntity.orderSource = orderEntity.channel.orderSource;
                channelEntity.channelOrderNo = orderEntity.channel.channelOrderNo;
            }
            // await ChannelEntity.save(channelEntity);

            await manager.save(channelEntity);
            const guestEntity = new Array<GuestEntity>();
            const guestCards = orderEntity.guest.map((c) => c.card);
            const guestCard = await GuestEntity.find({ where: { card: In(guestCards) } });
            const orderGuestEntity = new Array<OrderGuestEntity>()
            if (guestCard.length > 0) {
                log.guestId = guestCard[0].id;
                for (let i = 0; i < guestCard.length; i++) {
                    const order_guest = new OrderGuestEntity();
                    order_guest.orderId = order.id;
                    order_guest.guestId = guestCard[i].id;
                    orderGuestEntity.push(order_guest);
                }
            } else {
                for (let i = 0; i < orderEntity.guest.length; i++) {
                    const element = orderEntity.guest[i];
                    const guest = new GuestEntity();
                    guest.yourname = element.yourname;
                    guest.phone = element.phone;
                    guest.card = element.card;
                    guestEntity.push(guest);
                }

                // const item = await GuestEntity.save(guestEntity);
                const item = await manager.save(guestEntity);
                log.guestId = item[0].id;

                for (let i = 0; i < item.length; i++) {
                    const order_guest = new OrderGuestEntity();
                    order_guest.orderId = order.id;
                    order_guest.guestId = item[i].id;
                    orderGuestEntity.push(order_guest);
                }
            }

            // await OrderGuestEntity.save(orderGuestEntity);
            await manager.save(orderGuestEntity);
            const orderRoomEntity = new Array<OrderRoomEntity>();

            const roomTypeNmaes = orderEntity.roomType.map((c) => c.roomTypeName);
            const roomType = await RoomTypeEntity.find({ where: { roomTypeName: In(roomTypeNmaes) } });
            let num = 0;
            for (let i = 0; i < roomType.length; i++) {

                const element = roomType[i];
                content = content + "一间" + element.roomTypeName + ",金额" + element.roomPrice / 100 + ";";
                const order_room = new OrderRoomEntity();
                order_room.orderId = order.id;
                order_room.roomTypeId = element.id;
                order_room.currentPrice = element.roomPrice;
                orderRoomEntity.push(order_room);
                num = num + element.roomPrice;
            }

            // await OrderRoomEntity.save(orderRoomEntity);
            await manager.save(orderRoomEntity);

            content = content + "房价总额：" + num / 100 + "\n";
            content = content + "退/收款记录：" + "\n";
            const payLogEntity = new Array<OrderPaymentEntity>();
            for (let i = 0; i < orderEntity.payLog.length; i++) {
                const element = orderEntity.payLog[i];
                content = content + element.payType + "$" + element.payMoney + "[" + element.payWay + "]" + "\n";
                const payLog = new OrderPaymentEntity();
                payLog.orderId = order.id;
                payLog.payType = element.payType;
                payLog.payMoney = element.payMoney * 100;
                payLog.payWay = element.payWay;
                payLog.payTime = element.payTime;
                payLogEntity.push(payLog);

            }

            // await OrderPaymentEntity.save(payLogEntity);
            await manager.save(payLogEntity);

            log.content = content;

            // await LogEntity.save(log);
            await manager.save(log);
        });

        return true;

    }

    async updateOrder(orderEntity: OrderEntity) {

        const _orderEntity = new OrderEntity();
        _orderEntity.id = orderEntity.id;
        _orderEntity.orderNo = orderEntity.orderNo;
        _orderEntity.amount = orderEntity.amount * 100;
        _orderEntity.paidAmount = orderEntity.paidAmount * 100;
        _orderEntity.deposit = orderEntity.deposit * 100;
        _orderEntity.receivedDeposit = orderEntity.receivedDeposit * 100;
        _orderEntity.returnDeposit = orderEntity.returnDeposit * 100;
        _orderEntity.remark = orderEntity.remark;
        _orderEntity.startTime = orderEntity.startTime;
        _orderEntity.endTime = orderEntity.endTime;
        _orderEntity.payLog = orderEntity.payLog;
        _orderEntity.guest = orderEntity.guest;
        _orderEntity.roomType = orderEntity.roomType;
        _orderEntity.channel = orderEntity.channel;
        _orderEntity.userId = orderEntity.userId;
        _orderEntity.status = orderEntity.status;

        const _channel = new ChannelEntity();
        _channel.id = orderEntity.channel.id;
        _channel.orderId = orderEntity.channel.orderId;
        _channel.orderSource = orderEntity.channel.orderSource;
        _channel.channelOrderNo = orderEntity.channel.channelOrderNo;
        _channel.status = orderEntity.channel.status;

        let content = "修改后的订单：" + "\n";
        content = content + "【" + orderEntity.guest[0].yourname + "-" + orderEntity.guest[0].phone + "-" + orderEntity.guest[0].card + "】" + "《" + orderEntity.channel.orderSource + "》办理预定" + "\n" + orderEntity.startTime + "入住" + "\n预定:";

        // console.log(orderEntity);
        // orderEntity.amount = orderEntity.amount * 100;
        // orderEntity.paidAmount = orderEntity.paidAmount * 100;
        // orderEntity.deposit = orderEntity.deposit * 100;
        // orderEntity.receivedDeposit = orderEntity.receivedDeposit * 100;
        // orderEntity.returnDeposit = orderEntity.returnDeposit * 100;
        await getManager().transaction(async manager => {

            // await OrderEntity.save(orderEntity);
            // await ChannelEntity.save(orderEntity.channel);
            // await OrderRoomEntity.delete({ orderId: orderEntity.id });
            // await OrderGuestEntity.delete({ orderId: orderEntity.id });
            // await OrderPaymentEntity.delete({ orderId: orderEntity.id });

            await manager.save(_orderEntity);
            await manager.save(_channel);
            await OrderRoomEntity.delete({ orderId: orderEntity.id });
            await OrderGuestEntity.delete({ orderId: orderEntity.id });
            await OrderPaymentEntity.delete({ orderId: orderEntity.id });

            const orderRoomEntity = new Array<OrderRoomEntity>();

            const roomTypeNmaes = orderEntity.roomType.map((c) => c.roomTypeName);
            const roomType = await RoomTypeEntity.find({ where: { roomTypeName: In(roomTypeNmaes) } });
            let num = 0;
            for (let i = 0; i < roomType.length; i++) {
                const element = roomType[i];
                content = content + "一间" + element.roomTypeName + ",金额" + element.roomPrice / 100 + ";";
                const order_room = new OrderRoomEntity();
                order_room.orderId = orderEntity.id;
                order_room.roomTypeId = element.id;
                order_room.currentPrice = element.roomPrice;
                orderRoomEntity.push(order_room);
                num = num + element.roomPrice;
            }
            content = content + "房价总额：" + num / 100 + "\n";

            // await OrderRoomEntity.save(orderRoomEntity);
            await manager.save(orderRoomEntity);

            const payLogEntity = new Array<OrderPaymentEntity>();
            content = content + "退/收款记录：" + "\n";
            for (let i = 0; i < orderEntity.payLog.length; i++) {
                const element = orderEntity.payLog[i];
                content = content + element.payType + "$" + element.payMoney + "[" + element.payWay + "]" + "\n";
                const payLog = new OrderPaymentEntity();
                payLog.orderId = orderEntity.id;
                payLog.payType = element.payType;
                payLog.payMoney = element.payMoney * 100;
                payLog.payWay = element.payWay;
                payLog.payTime = element.payTime;
                payLogEntity.push(payLog);
            }

            // await OrderPaymentEntity.save(payLogEntity);
            await manager.save(payLogEntity);

            const guestCards = orderEntity.guest.map((c) => c.card);

            const guestCard = await GuestEntity.find({ where: { card: In(guestCards) } });
            console.log(guestCard);
            for (let i = 0; i < orderEntity.guest.length; i++) {
                const element = orderEntity.guest[i];
                const guest = guestCard.find(item => item.card == element.card);
                if (guest) {
                    continue;
                } else {
                    throw new HttpException({
                        message: 'Card is error',
                        error: 'orderNo must be unique',
                    },
                        HttpStatus.BAD_REQUEST);
                }
            }
            // console.log(content);
            const date = new Date();
            // const time = format(date,'YYYY-MM-DD HH:mm:ss');

            const log = new LogEntity();
            log.orderId = orderEntity.id;
            log.gmt_create = date;
            log.content = content;
            log.guestId = orderEntity.guest[0].id;
            // await LogEntity.save(log);
            await manager.save(log);
        })


        return true;
    }

    async findAll(): Promise<OrderEntity[]> {
        const orderEntity = await OrderEntity.find({ where: { status: 1 } });
        const orderEntityIds = orderEntity.map((c) => c.id);
        // console.log(orderEntityIds);

        const [userEntity, channelEntity, orderRoom, orderPayment, orderGuestList] = await Promise.all([
            UsersEntity.find({ where: { id: In(orderEntityIds) } }),
            ChannelEntity.find({ where: { orderId: In(orderEntityIds) } }),
            OrderRoomEntity.find({ where: { orderId: In(orderEntityIds) } }),
            OrderPaymentEntity.find({ where: { orderId: In(orderEntityIds) } }),
            OrderGuestEntity.find({ where: { orderId: In(orderEntityIds) } }),
        ])
        // console.log(channelEntity);
        // console.log(orderGuestList);

        const orderTypeIds = orderRoom.map((c) => c.roomTypeId);
        const orderRoomeIdS = orderRoom.map((c) => c.roomId);
        const orderGuestIds = orderGuestList.map((c) => c.guestId);

        const orderType = await RoomTypeEntity.find({ where: { id: In(orderTypeIds) } });
        for (let i = 0; i < orderType.length; i++) {
            orderType[i].roomPrice = orderType[i].roomPrice / 100;
        }
        const roomEntity = await RoomEntity.find({ where: { id: In(orderRoomeIdS) } });
        const orderGuest = await GuestEntity.find({ where: { id: In(orderGuestIds) } });


        for (let i = 0; i < orderEntity.length; i++) {
            const element = orderEntity[i];
            element.amount = element.amount / 100;
            element.paidAmount = element.paidAmount / 100;
            element.deposit = element.deposit / 100;
            element.receivedDeposit = element.receivedDeposit / 100;
            element.returnDeposit = element.returnDeposit / 100;

            // console.log(element.userId);
            // console.log(element);
            const item = userEntity.find(user => user.id == element.userId);
            const channel = channelEntity.find(channel => channel.orderId == element.id);

            if (channel) {
                element.channel = channel;
            }
            if (item) {
                element.users = item;
            }
            orderRoom.forEach(item => {
                if (element.id == item.orderId) {
                    const type = orderType.find(element => element.id == item.roomTypeId);
                    if (type) {
                        element.roomType.push(type);
                    }
                }
            })

            orderPayment.forEach(item => {
                if (element.id == item.orderId) {
                    item.payMoney = item.payMoney / 100;
                    element.payLog.push(item);
                }
            })

            orderGuestList.forEach(item => {
                if (element.id == item.orderId) {
                    const guest = orderGuest.find(element => element.id == item.guestId);
                    if (guest) {
                        element.guest.push(guest);
                    }
                }
            })

        }

        return orderEntity;
    }

    async findOne(orderNo: string): Promise<OrderEntity> {
        const orderEntity = await OrderEntity.find({ where: { status: 1 } });
        const orderEntityIds = orderEntity.map((c) => c.id);

        const [userEntity, channelEntity, orderRoom, orderPayment, orderGuestList] = await Promise.all([
            UsersEntity.find({ where: { id: In(orderEntityIds) } }),
            ChannelEntity.find({ where: { id: In(orderEntityIds) } }),
            OrderRoomEntity.find({ where: { orderId: In(orderEntityIds) } }),
            OrderPaymentEntity.find({ where: { orderId: In(orderEntityIds) } }),
            OrderGuestEntity.find({ where: { orderId: In(orderEntityIds) } }),
        ])
        // console.log(orderGuestList);

        const orderRoomIds = orderRoom.map((c) => c.roomTypeId);
        const orderGuestIds = orderGuestList.map((c) => c.guestId);

        const orderType = await RoomTypeEntity.find({ where: { id: In(orderRoomIds) } });
        for (let i = 0; i < orderType.length; i++) {
            orderType[i].roomPrice = orderType[i].roomPrice / 100;
        }

        const orderGuest = await GuestEntity.find({ where: { id: In(orderGuestIds) } });

        for (let i = 0; i < orderEntity.length; i++) {
            const element = orderEntity[i];
            element.amount = element.amount / 100;
            element.paidAmount = element.paidAmount / 100;
            element.deposit = element.deposit / 100;
            element.receivedDeposit = element.receivedDeposit / 100;
            element.returnDeposit = element.returnDeposit / 100;

            // console.log(element.userId);
            // console.log(element);
            const item = userEntity.find(user => user.id == element.userId);
            const channel = channelEntity.find(channel => channel.orderId == element.userId);
            if (item) {
                element.users = item;
            }
            if (channel) {
                element.channel = channel;
            }

            orderRoom.forEach(item => {
                if (element.id == item.orderId) {
                    const type = orderType.find(element => element.id == item.roomTypeId);
                    if (type) {
                        element.roomType.push(type);
                    }
                }
            })

            orderPayment.forEach(item => {
                if (element.id == item.orderId) {
                    item.payMoney = item.payMoney / 100;
                    element.payLog.push(item);
                }
            })

            orderGuestList.forEach(item => {
                if (element.id == item.orderId) {
                    const guest = orderGuest.find(element => element.id == item.guestId);
                    if (guest) {
                        element.guest.push(guest);
                    }
                }
            })

        }

        const temp = orderEntity.find(item => item.orderNo == orderNo);
        if (temp) {
            return temp;
        } else {
            throw new HttpException({
                message: 'Order is not exist',
                error: 'orderNo must be unique',
            },
                HttpStatus.BAD_REQUEST);
        }
    }

    async deleteOrder(orderNo: string): Promise<void> {
        const orderEntity = await OrderEntity.findOne({ where: { orderNo: orderNo } });
        if (orderEntity) {
            await OrderEntity.update(orderEntity.id, { status: 0 });
        } else {
            throw new HttpException({
                message: 'Order is not exist',
                error: 'orderNo must be unique',
            },
                HttpStatus.BAD_REQUEST);
        }
    }


    async getOne(startTime: Date) {
        // return await OrderEntity.find();
        // console.log(startTime.toString());
        // console.log(this.getNextDay(startTime.toString()))
        let time = startTime.toString();
        let roomStatus = new Array<Date>();
        for (let i = 0; i < 30; i++) {
            const date = new Date(time);
            roomStatus.push(date);
            time = this.getNextDay(time);
        }

        const orderEntity = await this.findAll();
        const orderList = new Array<OrderEntity>();
        for (let i = 0; i < orderEntity.length; i++) {
            const element = orderEntity[i];
            if (element.startTime <= roomStatus[roomStatus.length - 1]  && element.endTime > roomStatus[0]) {
                orderList.push(element);
            }
            // const order = orderEntity.find(item => item.startTime <= roomStatus[roomStatus.length - 1]);
        }
        // 
        // console.log(orderList);
        const order_roomIds = orderList.map((c) => c.id);
        // console.log(order_roomIds);


        const roomEntity = await RoomEntity.find();
        const order_room = await OrderRoomEntity.find({ where: { orderId: In(order_roomIds) } });
        // return order_room;
        // console.log(order_room);

        // console.log(roomStatus);
        // console.log(roomEntity);
        let arr = new Array(); //定义一维数组 
        for (let i = 0; i < roomEntity.length; i++) {
            const element = roomEntity[i];
            arr[i] = new Array(); //将每一个子元素又定义为数组
            for (let n = 0; n < roomStatus.length; n++) {
                const roomTime = new Date(roomStatus[n])
                // console.log(roomTime);
                let num = 0;
                for (let j = 0; j < order_room.length ;j++){
                    const item = order_room[j];
                    if(element.id == item.roomId && element.roomTypeId == item.roomTypeId){
                        const order = orderList.find((c) => c.id == item.orderId);
                        // console.log(order.startTime);
                        // break;
                        if(order.startTime.getTime() ==   roomTime.getTime()){
                            // console.log(1);s
                            arr[i][n] = order;
                            num = 1;
                        }
                    }
                }
                if(num == 0){
                    arr[i][n] = null;
                }

                //此时aa[i][n]可以看作是一个二级数组
            }
        }
        // console.log(arr);

        // return orderList;

        return {
            roomEntity,
            roomStatus,
            arr
        };
    }

    //-time 格式 yyyy-MM-dd
    getNextDay(time) {
        let date = new Date(time);
        // +1 可以换为其他前后天数
        date.setDate(date.getDate() + 1);
        let y = date.getFullYear();
        let m = date.getMonth() < 9 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
        let d = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
        return y + "-" + m + "-" + d;

    }

}